#pragma once;

#include <d3dx9.h>
#include <assert.h>

#include "rendrer.hpp"

namespace dexgel
{
namespace priv
{


#define SVertexType (D3DFVF_XYZ | D3DFVF_DIFFUSE)
#define LitVertexType (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL)
	// D3DFVF_XYZRHW means no tform will happen! Assumes verts are allready tformed!
//#define VertexTypeUV D3DFVF_XYZ | (1 << D3DFVF_TEXCOUNT_SHIFT) | D3DFVF_DIFFUSE
#define VertexTypeUV ( D3DFVF_XYZ | (1 << D3DFVF_TEXCOUNT_SHIFT) )

// Here is our 3D Object to handle all of our 3D needs -- It will create our needed D3D interfaces
// and allow us to render a list or vertices of a vertex type that we created.
// You'll notice that all of the functions/variables are static.  This is because 
// we only want ONE instance of the CD3DObj.  By making a variable or function static in a 
// class it insures that only one instance of that variable or function will be created.

class RendererDx : public Rendrer
{
	public:

		RendererDx() { /* do nothing */ } 

		static bool init(HWND hwnd); // Initializes our 3D Object

		virtual void begin(); // Begins a scene
		virtual void end(); // Ends a scene
		virtual bool render(Mesh * m);
		virtual bool render(SVertex *vertList, int numTris);
		virtual bool render(LitVertex *vertList, int numTris);
		virtual bool render(SVertex *vertList, int numVerts, unsigned short *indexList, int numIndices);
		virtual bool render(VertexUV *vertList, int numTris);
		virtual bool renderLine( SVertex *gVertPool, int numVerts );
		virtual bool clearColor(int color, float zDepth = 1.0f);
		virtual void setViewMatrix(const glm::vec3 &eye, const glm::vec3 &target);
		virtual void setViewMatrix(float* matrix);
		virtual void setProjMatrix(float fov, float aspectRatio, float nearClip, float farClip);
		virtual void setProjOrtho( float* projectionMtx );
		virtual void SetTransform( float* matWorld );
		
		virtual void setLightType(int which, DEXGELLIGHTTYPE type);
		virtual void setLightPos(int which, const glm::vec3 &pos);
		virtual void setLightDir(int which, const glm::vec3 &dir);
		virtual void setLightColor(int which, int diffuse, int specular, int ambient);
		virtual void setLightAttenuation(int which, float constant, float linear, float quad );
		virtual void setLightRange(int which, float r);
		virtual void setLightRadius(int which, float innerCone, float outerCone);
		virtual void setLightActive(int which, bool onOrOff);

		virtual void enableLighting() {
			mResult = mDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
			assert(mResult == D3D_OK);
		}
		virtual void disableLighting()
		{
			mResult = mDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
			assert(mResult == D3D_OK);
		}

		virtual Texture* loadTexture( const std::string filename );
		virtual Mesh*	 createMesh( SVertex* verts, int numVerts );
		virtual Mesh*	 createMesh( LitVertex* verts, int numVerts );

		static void deinit(); // Free up our 3D Object
		
		virtual ~RendererDx() { /* do nothing */ }; // Deconstuctor
		//static CD3DObj* instance();

		// This is the "mother" of all D3D interfaces.  We'll use this to create other
		// D3D objects/interfaces.
		// **NOTE** You may also see this defined as LPDIRECT3D9 or PDIRECT3D9 which
		//			are both typedefed to be pointers to a IDirect3D9 interface
		static IDirect3D9 *mInterface;
		
		// This is the D3D object that we'll use the most.  It is what gives up "direct" access
		// to the graphics card.  By using it we can render polygons, create resources, work 
		// with system-level variables, adjust gamma ramp levels, work with palettes, 
		// and create shaders.  For this tutorial, will use our D3D device to render a white
		// triangle to the screen.
		// **NOTE** You may also see this defined as LPDIRECT3DDEVICE9 or PDIRECT3DDEVICE9 which
		//			are both typedefed to be pointers to a IDirect3DDevice9 interface
		static IDirect3DDevice9 *mDevice;
		
	protected:
		static bool initLights();
		static void initShaders();

	private:
	
		static HRESULT mResult; // Used for error checking

		static int mMaxLights; // Maximum number of lights for the current display adapter
		static D3DLIGHT9 *mLights; // Array of possible lights 

		static ID3DXEffect *mEffect;

		// We make the copy constructor and assignment operator private because
		// we do NOT want anyone accidentally making a copy of this class
		//CD3DObj(const CD3DObj &obj) {}
		//CD3DObj& operator =(CD3DObj &obj) { return *this; }
		
		
};



}
}
